package com.luoke.util.myjdbc;

import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import com.luoke.util.myjdbc.util.DBUtil;
import lombok.Data;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
@Data
public class UpdateWrapper<T> {
    private StringBuffer sql = new StringBuffer();
    private List<String> params = new ArrayList<>();
    private Class<T> clazz;

    public UpdateWrapper<T> update(Class<T> clazz) {
        this.clazz = clazz;
        String simpleName = clazz.getSimpleName();
        String tableName = StrUtil.toUnderlineCase(simpleName);//转成下划线
        String update = SQLEnum.UPDATE + StrUtil.SPACE + tableName + StrUtil.SPACE;
        sql.append(update);
        return this;
    }

    public UpdateWrapper<T> update(String tableName) {
        String update = SQLEnum.UPDATE + StrUtil.SPACE + tableName + StrUtil.SPACE;
        sql.append(update);
        return this;
    }

    public UpdateWrapper<T> set(SFunction<T> sf, String var) {
        String fieldName = DBUtil.getFieldName(sf);
        String set = SQLEnum.SET + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        params.add(var);
        sql.append(set);
        return this;
    }

    public UpdateWrapper<T> set(T entity ,SFunction<T> ...ignores) {
        boolean isSet=false;
        boolean isIgnore=false;
        Class<?> clazz = entity.getClass();
        try {
            // 获取类的 Class 对象
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //因为实体类中有序列化所需要标记的字段，这里排除掉
                if (Modifier.isStatic(field.getModifiers())) {  //该方法用来判断是否是静态成员变量
                    continue; // 跳过静态字段
                }
                field.setAccessible(true); // 设置private字段可访问
                String columnName = StrUtil.toUnderlineCase(field.getName()); // 转换为下划线命名
                Object fieldValue = field.get(entity); // 获取字段值
                //排除过滤字段
                for (SFunction ignore : ignores) {
                    if(DBUtil.getFieldName(ignore).equals(columnName)){
                        isIgnore=true;
                        break;
                    }
                }
                if(isIgnore){
                    isIgnore=false;
                    continue;
                }
                if (!isSet && fieldValue != null) {
                    this.set(columnName, String.valueOf(fieldValue));
                    isSet = true;
                } else if (fieldValue != null) {
                    this.comma(columnName, String.valueOf(fieldValue));
                }
            }
        } catch (Exception e) {
            StaticLog.error(e.getMessage());
            throw new RuntimeException(e);
        }
        return this;
    }

    public UpdateWrapper<T> set(String fieldName, String var) {
        String set = SQLEnum.SET + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        params.add(var);
        sql.append(set);
        return this;
    }
    public UpdateWrapper<T> comma(SFunction<T> sf, String var) {
        if(StrUtil.isBlank(var))return this;
        String fieldName = DBUtil.getFieldName(sf);
        String set = SQLEnum.COMMA_SIGN.getValue() + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        params.add(var);
        sql.append(set);
        return this;
    }

    public UpdateWrapper<T> comma(String fieldName, String var) {
        if(StrUtil.isBlank(var))return this;
//        String fieldName = DBUtil.getFieldName(sf);
        String set = SQLEnum.COMMA_SIGN.getValue() + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        params.add(var);
        sql.append(set);
        return this;
    }

    public UpdateWrapper<T> where(SFunction<T> sf, String var) {
        String fieldName = DBUtil.getFieldName(sf);
        String where = SQLEnum.WHERE + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(where);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> where(String fieldName, String var) {
        String where = SQLEnum.WHERE + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(where);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> where(SFunction<T> sf, String var, SQLEnum sqlEnum) {
        String fieldName = DBUtil.getFieldName(sf);
        String where = SQLEnum.WHERE + StrUtil.SPACE + fieldName + sqlEnum.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(where);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> and(SFunction<T> sf, String var) {
        String fieldName = DBUtil.getFieldName(sf);
        String and = SQLEnum.AND + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(and);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> and(SFunction<T> sf, String var, SQLEnum sqlEnum) {
        String fieldName = DBUtil.getFieldName(sf);
        String and = SQLEnum.AND + StrUtil.SPACE + fieldName + sqlEnum.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(and);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> or(SFunction<T> sf, String var) {
        String fieldName = DBUtil.getFieldName(sf);
        String or = SQLEnum.OR + StrUtil.SPACE + fieldName + SQLEnum.EQ_SIGN.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(or);
        params.add(var);
        return this;
    }

    public UpdateWrapper<T> or(SFunction<T> sf, String var, SQLEnum sqlEnum) {
        String fieldName = DBUtil.getFieldName(sf);
        String or = SQLEnum.OR + StrUtil.SPACE + fieldName + sqlEnum.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(or);
        params.add(var);
        return this;
    }

    private UpdateWrapper<T> update(SFunction<T> sf, String var, SQLEnum sqlEnum) {
        String fieldName = DBUtil.getFieldName(sf);
        String or = SQLEnum.OR + StrUtil.SPACE + fieldName + sqlEnum.getValue() + SQLEnum.QUE_SIGN.getValue() + StrUtil.SPACE;
        sql.append(or);
        params.add(var);
        return this;
    }
}
